#pragma once

#include <cassert>
#include <vector>
#include <string>
#include <unordered_map>
#include <algorithm>

#include "../comm/log.hpp"
#include "../comm/util.hpp"

namespace ns_model
{
    using namespace std;
    using namespace ns_log;
    using namespace ns_util;

    struct Question
    {
        string number; // 题目编号
        string title;  // 标题
        string star;   // 题目难度
        int cpu_limit; // 时间限制
        int mem_limit; // 空间限制
        string desc;   // 题目描述
        string head;   // 用户代码
        string tail;   // 测试代码
    };
   const string questions_list = "./questions/questions.list";
   const string questions_path="./questions/";

    class Model
    {
    private:
        unordered_map<string, Question> questions;

    public:
        Model()
        {
            assert(LoadQuestionList(questions_list));
        }
        ~Model() {}

        bool LoadQuestionList(const string &questions_list)
        {
            ifstream in(questions_list);
            if (!in.is_open())
            {
                LOG(FALSE)<<"加载题目配置文件失败"<<endl;
                return false;

            }

            string line;
            while (getline(in, line))
            {
                vector<string> tokens;
                FileSplit::SplitString(line, &tokens, " ");

                if (tokens.size() != 5)
                {
                    LOG(ERROR)<<"加载部分代码失败"<<endl;
                    continue;
                }

                Question q;
                q.number=tokens[0];
                q.title=tokens[1];
                q.star=tokens[2];
                q.cpu_limit=atoi(tokens[3].c_str());
                q.mem_limit=atoi(tokens[4].c_str());
                // std::cout<<q.cpu_limit<<"#####"<<q.mem_limit<<std::endl;

                const string path=questions_path+q.number+"/";
                FileUtil::ReadFile(path+"desc.txt",&q.desc,true);
                FileUtil::ReadFile(path+"head.cpp",&q.head,true);
                FileUtil::ReadFile(path+"tail.cpp",&q.tail,true);

                questions[q.number]=q;

            }
            LOG(INFO)<<"加载题库成功！！！！"<<endl;
            in.close();
            return true;
        }
        bool GetAllQuestions(vector<Question> *out)
        {
            if (questions.size() == 0)
            {
                LOG(ERROR)<<"加载全部题库出错"<<endl;
                return false;

            }
            for (auto &x : questions)
            {
                out->push_back(x.second);
            }
            sort(out->begin(),out->end(),[](const  Question& a,const Question& b){
                return  atoi(a.number.c_str()) <atoi(b.number.c_str());
            });
            return true;
        }
        bool GetOneQuestion(const string &number, Question *q)
        {
            if (questions.count(number))
            {
                (*q) = questions[number];
                return true;
            }
            LOG(ERROR)<<"加载部分题库出错"<<endl;
            return false;
        }
    };
}